home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / Talking KeyBoard / Source / speech.c < prev    next >
Encoding:
Text File  |  1998-06-19  |  8.2 KB  |  305 lines  |  [TEXT/CWIE]

  1. // Program Author: Paul Baxter
  2. //    pbaxter@assistivetech.com
  3. //
  4. //
  5.  
  6. #include <Retrace.h>
  7. #include <DeskBus.h>
  8. #include <Speech.h>
  9. #include <Ctype.h>
  10. #include <String.h>
  11.  
  12. #include "pref.h"
  13. #include "globals.h"
  14. #include "speech.h"
  15.  
  16. static Boolean isEndofWord(char ch);
  17. static Boolean isEndofSentence(char ch);
  18.  
  19. // * ****************************************************************************** *
  20. // *         AppendCharBuffer
  21. // *                 Add a KeyCode to the char buffer
  22. // *                  This gets called during a keyboard interupt after A5 is set.
  23. // *                gPrefs and gPronounce MUST be locked!!
  24. // * ****************************************************************************** *
  25. void AppendCharBuffer(char theKey)
  26. {
  27.     short index, pindex;
  28.     StringPtr theString;
  29.  
  30.     if ((**gPrefs).speakChars) {
  31.         if (gCharIndex >= kCharBuffSize -1) {
  32.             BlockMoveData(&gCharBuffer[1], gCharBuffer, kCharBuffSize -1);
  33.             gCharIndex = kCharBuffSize -1;
  34.         }
  35.         gCharBuffer[gCharIndex] = ' ';
  36.         gCharIndex++;
  37.         pindex = gPronounceIndex[theKey];
  38.         if (pindex != -1) {
  39.             if (gShiftState)
  40.                 theString = gPronounce[pindex].shiftpronounciation;
  41.             else
  42.                 theString = gPronounce[pindex].pronounciation;
  43.  
  44.             for (index = 1; index <= theString[0]; index++) {
  45.                 if (gCharIndex >= kCharBuffSize -1) {
  46.                     BlockMoveData(&gCharBuffer[1], gCharBuffer, kCharBuffSize -1);
  47.                     gCharIndex = kCharBuffSize -1;
  48.                 }
  49.                 gCharBuffer[gCharIndex] = theString[index];
  50.                 gCharIndex++;
  51.             }
  52.             return;
  53.         }
  54.         // we don't know what this is??
  55.         gCharIndex = 0;
  56.     }
  57. }
  58.  
  59. // * ****************************************************************************** *
  60. // *    AppendWordBuffer
  61. // *             Add a char to the word buffer
  62. // * ****************************************************************************** *
  63. void AppendWordBuffer(char theChar)
  64. {
  65.  
  66.     if (gWordIndex > 0 && isEndofWord(gWordBuffer[gWordIndex -1]))
  67.         return;
  68.  
  69.     if (!isEndofWord(theChar) && !isprint(theChar) && theChar != kDelete)
  70.         return;
  71.  
  72.     if ((**gPrefs).speakWords) {
  73.         // We could do something with arrow keys as well
  74.         if (theChar == kDelete) {
  75.             if (gWordIndex > 0)
  76.                 gWordIndex--;
  77.             return;
  78.         }
  79.         if (gWordIndex >= kWordBuffSize -1) {
  80.             BlockMoveData(&gWordBuffer[1], gWordBuffer, kWordBuffSize -1);
  81.             gWordIndex = kWordBuffSize -1;
  82.         }
  83.         gWordBuffer[gWordIndex] = theChar;
  84.         gWordIndex++;
  85.     }
  86. }
  87.  
  88. // * ****************************************************************************** *
  89. // *    AppendSentenceBuffer
  90. // *             Add a char to the sentence buffer
  91. // * ****************************************************************************** *
  92. void AppendSentenceBuffer(char theChar)
  93. {
  94.     if (gSentenceIndex > 0 && isEndofSentence(gSentenceBuffer[gSentenceIndex -1]))
  95.         return;
  96.  
  97.     if (!isEndofSentence(theChar) && !isprint(theChar) && theChar != kDelete)
  98.         return;
  99.  
  100.     if ((**gPrefs).speakSentence) {
  101.         if (theChar == kDelete) {
  102.             if (gSentenceIndex > 0)
  103.                 gSentenceIndex--;
  104.             return;
  105.         }
  106.         if (gSentenceIndex >= kSentenceBuffSize -1) {
  107.             BlockMoveData(&gSentenceBuffer[1], gSentenceBuffer, kSentenceBuffSize -1);
  108.             gSentenceIndex = kSentenceBuffSize -1;
  109.         }
  110.         gSentenceBuffer[gSentenceIndex] = theChar;
  111.         gSentenceIndex++;
  112.     }
  113. }
  114.  
  115. // * ****************************************************************************** *
  116. // *    SpeakChars
  117. // *                speak chars in the char buffer
  118. // * ****************************************************************************** *
  119. void SpeakChars(void)
  120. {
  121.     if (((**gPrefs).speakChars) && (gCharIndex) && (gSpeechChannel)) {
  122.         // give chars precedence over all others
  123.         gLastSpeechChar = true;
  124.          SpeakText(gSpeechChannel, gCharBuffer, gCharIndex);
  125.         gCharIndex = 0;
  126.     }
  127. }
  128.  
  129. // * ****************************************************************************** *
  130. // *     SpeakWords
  131. // *             speak any words in the word buffer
  132. // * ****************************************************************************** *
  133. void SpeakWords(void)
  134. {
  135.     short wordindex;
  136.  
  137.     if ((**gPrefs).speakChars && gWordIndex == 1)
  138.         gWordIndex = 0;    // avoid garble
  139.  
  140.     if (((**gPrefs).speakWords) && (gWordIndex) && (gSpeechChannel)) {
  141.         wordindex = gWordIndex;
  142.         gWordIndex = gCharIndex = 0;
  143.         gLastSpeechChar = false;
  144.           SpeakText(gSpeechChannel, gWordBuffer, wordindex);
  145.     }
  146. }
  147.  
  148. // * ****************************************************************************** *
  149. // *     SpeakSentences
  150. // *             speak any sentences in the sentence buffer
  151. // * ****************************************************************************** *
  152. void SpeakSentences(void)
  153. {
  154.     if ((gSentenceIndex == 1) && ((**gPrefs).speakChars || (**gPrefs).speakWords))
  155.         gSentenceIndex = 0;    // avoid garble
  156.  
  157.     if (((**gPrefs).speakSentence) && (gSentenceIndex) && (gSpeechChannel)) {
  158.         gLastSpeechChar = false;
  159.           SpeakText(gSpeechChannel, gSentenceBuffer, gSentenceIndex);
  160.         gWordIndex = 0;    // avoid garble
  161.         gCharIndex = 0;    // avoid garble
  162.         gSentenceIndex = 0;
  163.     }
  164. }
  165.  
  166. // * ****************************************************************************** *
  167. // *     isEndofSentence
  168. // *                            is the char an end of sentence marker
  169. // * ****************************************************************************** *
  170. static Boolean isEndofSentence(char ch)
  171. {
  172.     switch (ch) {
  173.         case '.':
  174.         case '?':
  175.         case '!':
  176.         case ';':
  177.         case 0x03:        // enter
  178.         case 0x0D:        // return
  179.         case 0x1C:        // left arrow
  180.         case 0x1D:        // right arrow
  181.         case 0x1E:        // up arrow
  182.         case 0x1F:        // down arrow
  183.             return true;
  184.  
  185.         default:
  186.             return false;
  187.     }
  188. }
  189.  
  190. // * ****************************************************************************** *
  191. // *     isEndofWord
  192. // *                            is the char an end of word marker
  193. // * ****************************************************************************** *
  194. static Boolean isEndofWord(char ch)
  195. {
  196.     switch (ch) {
  197.         case ' ':
  198.         case '.':
  199.         case '?':
  200.         case '!':
  201.         case ';':
  202.         case ',':
  203.         case '@':
  204.         case '#':
  205.         case '$':
  206.         case '%':
  207.         case '^':
  208.         case '&':
  209.         case '*':
  210.         case '(':
  211.         case ')':
  212.         case '-':
  213.         case '+':
  214.         case '=':
  215.         case '[':
  216.         case ']':
  217.         case '{':
  218.         case '}':
  219.         case ':':
  220.         case '\"':
  221.         case 0x03:        // enter
  222.         case 0x0D:        // return
  223.         case 0x1C:        // left arrow
  224.         case 0x1D:        // right arrow
  225.         case 0x1E:        // up arrow
  226.         case 0x1F:        // down arrow
  227.             return true;
  228.         default:
  229.             return false;
  230.     }
  231. }
  232.  
  233. // * ****************************************************************************** *
  234. // *     SpeakBuffers
  235. // *                            Speak Appropriate buffer
  236. // * ****************************************************************************** *
  237. void SpeakBuffers(void)
  238. {
  239.     if (((**gPrefs).speakSentence) && (gSentenceIndex > 0) && 
  240.                 (isEndofSentence(gSentenceBuffer[gSentenceIndex -1])))
  241.         SpeakSentences();
  242.  
  243.     if (((**gPrefs).speakWords) && (gWordIndex > 0) && 
  244.                 (isEndofWord(gWordBuffer[gWordIndex -1])))
  245.         SpeakWords();
  246.  
  247.     SpeakChars();
  248. }
  249.  
  250.  
  251. // * ****************************************************************************** *
  252. // *     InitSpeechStrings
  253. // *             init speech strings
  254. // * ****************************************************************************** *
  255. void InitSpeechStrings(void)
  256. {
  257.     Handle ascihandle;
  258.     short count;
  259.     // Get names for Plaintalk
  260.     ascihandle = GetResource('ASCI', 128);
  261.     if (ascihandle) {
  262.         HLockHi(ascihandle);
  263.         DetachResource(ascihandle);
  264.         gPronounce = (KeyPronunciation*) (*ascihandle);
  265.         gNumPronounces = GetHandleSize(ascihandle) / sizeof(KeyPronunciation);
  266.  
  267.         // build indexes  into speach
  268.         memset(gPronounceIndex, -1, kNumKeys);
  269.         for (count = 0; count < gNumPronounces; count++)
  270.             gPronounceIndex[gPronounce[count].keyCode] = count;
  271.     }
  272. }
  273.  
  274. // * ****************************************************************************** *
  275. // *     InitBuffers
  276. // *             init speech buffers
  277. // * ****************************************************************************** *
  278. Boolean InitBuffers(void)
  279. {
  280.     // allocate our buffers
  281.     gCharBuffer = NewPtrSys(kCharBuffSize);
  282.     gWordBuffer = NewPtrSys(kWordBuffSize);
  283.     gSentenceBuffer = NewPtrSys(kSentenceBuffSize);
  284.     return (gCharBuffer && gWordBuffer && gSentenceBuffer);
  285. }
  286.  
  287. // * ****************************************************************************** *
  288. // *     KillBuffers
  289. // *             kill speech buffers
  290. // * ****************************************************************************** *
  291. void KillBuffers(void)
  292. {
  293.     if (gCharBuffer)
  294.         DisposePtr(gCharBuffer);
  295.     if (gWordBuffer)
  296.         DisposePtr(gWordBuffer);
  297.     if (gSentenceBuffer)
  298.         DisposePtr(gSentenceBuffer);
  299.     if (gPronounce)
  300.         DisposeHandle(RecoverHandle((Ptr)gPronounce));
  301.  
  302.     gCharBuffer = gWordBuffer = gSentenceBuffer = (Ptr)gPronounce = nil;
  303. }
  304.  
  305.